package org.yaac.client.activity;

import static com.google.common.base.Strings.isNullOrEmpty;

import java.util.List;

import javax.inject.Inject;

import org.yaac.client.place.EditorPlace;
import org.yaac.client.service.CRUDServiceAsync;
import org.yaac.client.ui.EditorView;
import org.yaac.client.util.ExceptionManager;
import org.yaac.client.widget.BlockingAsyncCallback;
import org.yaac.shared.editor.EntityHierarchy;
import org.yaac.shared.editor.EntityUpdateInfo;
import org.yaac.shared.property.KeyInfo;


import com.google.gwt.event.shared.EventBus;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.AcceptsOneWidget;

/**
 * @author Max Zhu (thebbsky@gmail.com)
 *
 */
public class EditorActivity extends SinglePlaceActivity<EditorPlace> {

	private final EditorView view;
	
	private final CRUDServiceAsync service;
	
	private final ExceptionManager exceptionManager;
	
	/**
	 * used ONLY to init view and data
	 * 
	 * after that key string will be loaded from view as it is possible people change it
	 */
	private String initKeyString;
	
	@Inject
	EditorActivity(EditorView view,
			CRUDServiceAsync service, 
			ExceptionManager exceptionManager) {
		super();
		this.view = view;
		this.service = service;
		this.exceptionManager = exceptionManager;
	}

	
	@Override
	public void start(AcceptsOneWidget containerWidget, EventBus eventBus) {
		view.setPresenter(this);
		containerWidget.setWidget(view.asWidget());
		
		if (!isNullOrEmpty(initKeyString)) {
			view.setKeyString(initKeyString);
			startLoad(initKeyString);
		}
	}

	@Override
	public SinglePlaceActivity<EditorPlace> withPlace(EditorPlace place) {
		this.initKeyString = place.getKeyString();
		return this;
	}

	public void startLoad(String keyString) {
		service.loadEntityHierarchy(keyString, 
				new BlockingAsyncCallback<EntityHierarchy>() {
					@Override
					public void onBlockingCallSuccess(EntityHierarchy result) {
						view.onDataReady(result);
					}

					@Override
					public void onBlockingCallFailure(Throwable caught) {
						exceptionManager.handle(caught);
					}
				}
		);
	}

	public void update(List<EntityUpdateInfo> changedEntities) {
		service.updateEntity(changedEntities, new AsyncCallback<Void>() {
			
			@Override
			public void onSuccess(Void result) {
				// refresh data again
				startLoad(view.getKeyString());
			}
			
			@Override
			public void onFailure(Throwable caught) {
				exceptionManager.handle(caught);
			}
		});
	}


	public void delete(KeyInfo key) {
		service.delete(key, new BlockingAsyncCallback<Void>() {
			@Override
			public void onBlockingCallSuccess(Void r) {
				// refresh data again
				startLoad(view.getKeyString());
			}

			@Override
			public void onBlockingCallFailure(Throwable caught) {
				exceptionManager.handle(caught);
			}
		});
	}


	public void copyToNew(KeyInfo keyInfo) {
		service.copyToNew(keyInfo, new BlockingAsyncCallback<String>() {
			@Override
			public void onBlockingCallSuccess(String result) {
				// refresh data again
				view.setKeyString(result);	// update key string
				startLoad(view.getKeyString());
			}

			@Override
			public void onBlockingCallFailure(Throwable caught) {
				exceptionManager.handle(caught);
			}
		});
	}


	public void create(KeyInfo key) {
		service.create(key, new BlockingAsyncCallback<Void>() {

			@Override
			public void onBlockingCallSuccess(Void result) {
				startLoad(view.getKeyString());
			}

			@Override
			public void onBlockingCallFailure(Throwable caught) {
				exceptionManager.handle(caught);
			}
		});
	}
}
